package com.code.web.user;

import com.code.commons.annotations.LoginAuth;
import com.code.commons.web.annotations.RateLimit;
import com.code.commons.web.annotations.ResponseResult;
import com.code.commons.web.annotations.SuperAdmin;
import com.code.commons.web.annotations.SystemProtect;
import com.code.model.bo.AppUpgradeBO;
import com.code.model.vo.login.LoginCredentialVO;
import com.code.model.vo.user.ModifyPhoneVO;
import com.code.model.vo.user.RegisterUserVO;
import com.code.model.vo.user.TranPwdVO;
import com.code.model.vo.user.UserRecommenderVO;
import com.code.service.UserService;
import com.code.user.model.bo.*;
import com.code.user.model.po.*;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

/**
 * 用户管理控制器
 *
 * @author tangyifei
 * @since 2019年12月25日18:15:16
 */
@ResponseResult
@RestController("userController")
@RequestMapping("/users")
public class UserController {

    @Resource
    private UserService userService;

    @ApiOperation(value = "注册用户", response = User.class, notes = "注册用户", httpMethod = "POST")
    @PostMapping
    @RateLimit(key = "limitRegisterUser")
    public User registerUser(@Validated @RequestBody RegisterUserVO user) {
        return userService.registerUser(user);
    }

    @ApiOperation(value = "APP更新", response = AppUpgradeBO.class, notes = "APP更新", httpMethod = "PATCH")
    @PatchMapping("/upgrade-app")
    @RateLimit(key = "limitUpgradeApp")
    public AppUpgradeBO upgradeApp() {
        return userService.upgradeApp();
    }

    @ApiOperation(value = "发送验证码", notes = "发送验证码", httpMethod = "GET")
    @GetMapping("/sms/{phone}/{category}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "category", value = "发送验证码的种类 1代表发送注册验证码 2代表发送找回密码时的验证码 3修改手机号发送的验证码 4修改交易密码发送的验证码 5修改登陆密码发送的验证码 6执行提币操作发送的验证码 7站内转账验证码", dataType = "int", paramType = "path", required = true),
            @ApiImplicitParam(name = "areaNo", value = "区号", dataType = "String", paramType = "query", required = false),
            @ApiImplicitParam(name = "phoneIndex", value = "手机号标识 默认为0，修改手机号时，发送新手机号验证码时传入1", dataType = "int", paramType = "query", required = false),
            @ApiImplicitParam(name = "recommendPhone", value = "推荐人手机号", dataType = "String", paramType = "query", required = false)
    })
    @RateLimit(key = "limitSendAuthCode", count = 1, time = 2)
    public void sendAuthCode(@PathVariable("phone") String phone, @PathVariable("category") int category,
                             @RequestParam(value = "areaNo", required = false) String areaNo, @RequestParam(value = "phoneIndex", required = false) Integer phoneIndex, @RequestParam(value = "recommendPhone", required = false) String recommendPhone) throws Exception {
        userService.sendAuthCode(phone, category, areaNo, phoneIndex, recommendPhone);
    }

    @ApiOperation(value = "验证注册验证码", notes = "验证注册验证码", httpMethod = "POST")
    @PostMapping("/{phone}/{authCode}/{areaNo}/verify-register-auth-code")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "authCode", value = "验证码", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "areaNo", value = "区号", dataType = "String", paramType = "path", required = true)
    })
    @RateLimit(key = "limitVerifyRegisterAuthCode", count = 1, time = 2)
    public Boolean verifyRegisterAuthCode(@PathVariable("phone") String phone, @PathVariable("authCode") String authCode, @PathVariable("areaNo") String areaNo) throws Exception {
        return userService.verifyRegisterAuthCode(phone, authCode, areaNo);
    }

    @ApiOperation(value = "用户登录", response = LoginToken.class, notes = "用户登录", httpMethod = "POST")
    @PostMapping("/login")
    @RateLimit(key = "limitDoLogin")
    public LoginToken doLogin(@Validated @RequestBody LoginCredentialVO loginCredentialVO) {
        return userService.login(loginCredentialVO);
    }

    @ApiOperation(value = "用户登录无需输入密码", response = LoginToken.class, notes = "用户登录无需输入密码", httpMethod = "POST")
    @PostMapping("/login/no-pwd")
    @LoginAuth
    @RateLimit(key = "limitLoginNoPwd")
    public LoginToken doLoginNoPwd(@Validated @RequestBody LoginCredentialVO loginCredentialVO) {
        return userService.doLoginNoPwd(loginCredentialVO);
    }

    @ApiOperation(value = "退出登录", notes = "退出登录", httpMethod = "POST")
    @PostMapping("/logout")
    @LoginAuth
    @RateLimit(key = "limitLogout")
    public void logout() {
        userService.logout();
    }

    @ApiOperation(value = "找回密码", notes = "找回密码", httpMethod = "PATCH")
    @PatchMapping("/find-pwd")
    @RateLimit(key = "limitFindPwd")
    public void findPwd(@Validated @RequestBody RegisterUserVO user) {
        userService.findPwd(user);
    }

    @ApiOperation(value = "验证找回密码验证码", notes = "验证找回密码验证码", httpMethod = "POST")
    @PostMapping("/{phone}/{authCode}/verify-find-pwd-auth-code")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "authCode", value = "验证码", dataType = "String", paramType = "path", required = true)
    })
    @RateLimit(key = "limitVerifyFindPwdAuthCode")
    public Boolean verifyFindPwdAuthCode(@PathVariable("phone") String phone, @PathVariable("authCode") String authCode) throws Exception {
        return userService.verifyFindPwdAuthCode(phone, authCode);
    }

    @ApiOperation(value = "重置密码", notes = "重置密码", httpMethod = "PATCH")
    @PatchMapping("/reset-pwd")
    @LoginAuth
    @RateLimit(key = "limitResetPwd")
    public void resetPwd(@Validated @RequestBody RegisterUserVO user) {
        userService.resetPwd(user);
    }

    @ApiOperation(value = "上传头像", notes = "上传头像", response = LoginToken.class, httpMethod = "POST")
    @PostMapping("/upload-avatar")
    @LoginAuth
    @RateLimit(key = "limitUploadAvatar")
    public LoginToken uploadAvatar(@RequestParam("file") MultipartFile file) {
        return userService.uploadAvatar(file);
    }

    @ApiOperation(value = "修改个人信息（修改昵称、头像、用户等级）", notes = "修改个人信息（修改昵称、头像   、用户等级）", response = LoginToken.class, httpMethod = "PATCH")
    @PatchMapping("/modify-personal-info")
    @LoginAuth
    @RateLimit(key = "limitModifyPersonalInfo")
    public LoginToken modifyPersonalInfo(@Validated @RequestBody LoginUser loginUser) {
        return userService.modifyPersonalInfo(loginUser);
    }

    @ApiOperation(value = "修改手机号", notes = "修改手机号", response = LoginToken.class, httpMethod = "PATCH")
    @PatchMapping("/modify-phone")
    @LoginAuth
    @RateLimit(key = "limitModifyPhone")
    public LoginToken modifyPhone(@Validated @RequestBody ModifyPhoneVO modifyPhoneVO) {
        return userService.modifyPhone(modifyPhoneVO);
    }

    @ApiOperation(value = "修改交易密码", notes = "修改交易密码", response = LoginToken.class, httpMethod = "PATCH")
    @PatchMapping("/modify-tran-pwd")
    @LoginAuth
    @RateLimit(key = "limitModifyTranPwd")
    public LoginToken modifyTranPwd(@Validated @RequestBody TranPwdVO tranPwdVO) {
        return userService.modifyTranPwd(tranPwdVO);
    }

    @ApiOperation(value = "重置交易密码", notes = "重置交易密码", response = LoginToken.class, httpMethod = "PATCH")
    @PatchMapping("/reset-tran-pwd")
    @LoginAuth
    @RateLimit(key = "limitResetTranPwd")
    public LoginToken resetTranPwd(@Validated @RequestBody TranPwdVO tranPwdVO) {
        return userService.resetTranPwd(tranPwdVO);
    }

    @ApiOperation(value = "设置交易密码", notes = "设置交易密码", response = LoginToken.class, httpMethod = "PATCH")
    @PatchMapping("/set-tran-pwd")
    @LoginAuth
    @RateLimit(key = "limitSetTranPwd")
    public LoginToken setTranPwd(@Validated @RequestBody TranPwdVO tranPwdVO) {
        return userService.setTranPwd(tranPwdVO);
    }

    @ApiOperation(value = "用户获取币种地址", notes = "用户获取币种地址", httpMethod = "GET")
    @GetMapping("/{userId}/get-coin-address")
    @LoginAuth
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户主键", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "coinType", value = "币种类型(XWC)", defaultValue = "XWC", dataType = "String", paramType = "query", required = true)
    })
    @RateLimit(key = "limitGetCoinAddress")
    public String getCoinAddress(@PathVariable("userId") String userId, @RequestParam("coinType") String coinType) throws Exception {
        return userService.getCoinAddress(userId, coinType);
    }

    @ApiOperation(value = "获取用户的入金通道列表（弹出入金窗口调用的API）", response = UserAZPlanChannel.class, notes = "获取用户的入金通道列表（弹出入金窗口调用的API）", httpMethod = "GET")
    @GetMapping("/{userId}/AZPlanChannels")
    @LoginAuth
    @SystemProtect
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户主键", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "coinType", value = "币种类型", dataType = "String", paramType = "query", required = true)
    })
    @RateLimit(key = "limitGetAZPlanChannelList")
    public Map<String, Object> getAZPlanChannelList(@PathVariable("userId") String userId, @RequestParam("coinType") String coinType) {
        return userService.getAZPlanChannelList(userId, coinType);
    }

    @ApiOperation(value = "用户内部充值（内部转入）和内部转出（扣除）", notes = "用户内部充值（内部转入）和内部转出（扣除）", httpMethod = "POST")
    @PostMapping("/inner-recharge")
    @LoginAuth
    @SuperAdmin
    public int recharge(@RequestBody RechargeTranRecord rechargeTranRecord) throws Exception {
        return userService.recharge(rechargeTranRecord);
    }

    @ApiOperation(value = "获取某一个用户钱包列表", response = UserCoinBalance.class, notes = "获取某一个用户钱包列表", httpMethod = "GET")
    @GetMapping("/{userId}/get-user-wallet-list")
    @LoginAuth
//    @SuperAdmin
    public List<UserCoinBalance> getUserCoinBalanceList(@PathVariable("userId") String userId) {
        return userService.getUserCoinBalanceList(userId);
    }

    @ApiOperation(value = "跳转邀请用户注册页面获取推荐人矿池的当前版本号和USDT钱包的账户版本号", response = UserCoinBalanceBO.class, notes = "跳转邀请用户注册页面获取推荐人矿池的当前版本号和USDT钱包的账户版本号", httpMethod = "GET")
    @GetMapping("/{recommenderPhone}/get-usdt-version")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "recommenderPhone", value = "推荐人用户手机号", dataType = "String", paramType = "path", required = true)
    })
    @Deprecated
    public UserCoinBalanceBO getUsdtVersion(@PathVariable("recommenderPhone") String recommenderPhone) {
        return userService.getUsdtVersion(recommenderPhone);
    }

    @ApiOperation(value = "获取用户详情", response = User.class, notes = "获取用户详情", httpMethod = "GET")
    @GetMapping("/{userId}/get-user-detail")
    @LoginAuth
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "用户主键", dataType = "String", paramType = "path", required = true),
    })
    @RateLimit(key = "limitGetUserDetail")
    public User getUserDetail(@PathVariable("userId") String userId) {
        return userService.getUserDetail(userId);
    }

    @ApiOperation(value = "获取推荐人的直推用户列表", response = UserRecommenderVO.class, notes = "获取推荐人的直推用户列表", httpMethod = "GET")
    @GetMapping("/{userId}/recommends")
    @LoginAuth
    @ApiImplicitParams({
            @ApiImplicitParam(name = "userId", value = "推荐人的用户主键", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "entryMoneyState", value = "有无入金", dataType = "int", paramType = "query", required = false),
            @ApiImplicitParam(name = "page", value = "当前页", dataType = "int", paramType = "query", required = false),
            @ApiImplicitParam(name = "pageSize", value = "每页的大小", dataType = "int", paramType = "query", required = false),
    })
    @RateLimit(key = "limitGetRecommendsByUserId")
    public Map<String, Object> getRecommendsByUserId(@PathVariable("userId") String userId,
                                                     @RequestParam(value = "entryMoneyState", required = false) Integer entryMoneyState,
                                                     @RequestParam(value = "page", required = false) Integer page,
                                                     @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        return userService.getRecommendsByUserId(userId, entryMoneyState, page, pageSize);
    }

    @ApiOperation(value = "获取推荐人的直推用户列表", response = UserRecommenderVO.class, notes = "获取推荐人的直推用户列表", httpMethod = "GET")
    @GetMapping("/{phone}/recommends-by-phone")
    @LoginAuth
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "推荐人的手机号", dataType = "String", paramType = "path", required = true),
            @ApiImplicitParam(name = "entryMoneyState", value = "有无入金", dataType = "int", paramType = "query", required = false),
            @ApiImplicitParam(name = "page", value = "当前页", dataType = "int", paramType = "query", required = false),
            @ApiImplicitParam(name = "pageSize", value = "每页的大小", dataType = "int", paramType = "query", required = false),
    })
    @RateLimit(key = "limitGetRecommendsByPhone")
    public Map<String, Object> getRecommendsByPhone(@PathVariable("phone") String phone,
                                                    @RequestParam(value = "entryMoneyState", required = false) Integer entryMoneyState,
                                                    @RequestParam(value = "page", required = false) Integer page,
                                                    @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        return userService.getRecommendsByPhone(phone, entryMoneyState, page, pageSize);
    }

    @ApiOperation(value = "提交用户认证", response = LoginToken.class, notes = "提交用户认证", httpMethod = "POST")
    @PostMapping("/user-certifications")
    @LoginAuth
    @RateLimit(key = "limitAddUserCertification")
    public LoginToken addUserCertification(@Validated @RequestBody UserCertification userCertification) {
        return userService.addUserCertification(userCertification);
    }

    @ApiOperation(value = "通过用户主键获取用户认证详情", response = UserCertification.class, notes = "通过用户主键获取用户认证详情", httpMethod = "GET")
    @GetMapping("/{userId}/user-certifications")
    @LoginAuth
    @RateLimit(key = "limitGetUserCertificationByUserId")
    public UserCertification getUserCertificationByUserId(@PathVariable("userId") String userId) {
        return userService.getUserCertificationByUserId(userId);
    }

    /**
     * 获取用户认证列表
     *
     * @param userCertificationBO 用户认证查询对象
     * @return 用户认证列表
     */
    @ApiOperation(value = "获取用户认证列表", response = UserCertificationBO.class, notes = "获取用户认证列表", httpMethod = "POST")
    @LoginAuth
    @RateLimit(key = "limitGetUserCertificationList")
    @PostMapping("/user-certification-list")
    public UserCertificationBO getUserCertificationList(@RequestBody UserCertificationBO userCertificationBO) {
        return userService.getUserCertificationList(userCertificationBO);
    }

    /**
     * 更新用户认证信息
     *
     * @param userCertification 用户认证对象
     * @return 影响的行数
     */
    @ApiOperation(value = "更新用户认证信息", notes = "更新用户认证信息", httpMethod = "PATCH")
    @LoginAuth
    @RateLimit(key = "limitUpdateUserCertification")
    @PatchMapping("/user-certifications")
//    @SuperAdmin
    public int updateUserCertification(@RequestBody UserCertification userCertification) {
        return userService.updateUserCertification(userCertification);
    }

    @ApiOperation(value = "上传图片", notes = "上传图片", httpMethod = "POST")
    @PostMapping("/upload-photo")
    @LoginAuth
    @RateLimit(key = "limitUploadPhoto")
    public String uploadPhoto(@RequestParam("file") MultipartFile file) {
        return userService.uploadPhoto(file);
    }

    /**
     * 更新系统维护开关
     *
     * @param systemSettingBO 系统维护业务对象
     * @return 影响的行数
     */
    @ApiOperation(value = "更新系统维护开关", notes = "更新系统维护开关", httpMethod = "PATCH")
    @LoginAuth
    @RateLimit(key = "limitUpdateSystemProtect")
    @PatchMapping("/system-protect")
    @SuperAdmin
    public int updateSystemProtect(@RequestBody SystemSettingBO systemSettingBO) {
        return userService.updateSystemProtect(systemSettingBO);
    }

    /**
     * 获取系统维护开关状态
     *
     * @return 系统维护开关状态
     */
    @ApiOperation(value = "获取系统维护开关状态", notes = "获取系统维护开关状态", httpMethod = "GET")
    @LoginAuth
    @RateLimit(key = "limitGetSystemProtect")
    @GetMapping("/system-protect")
    public String getSystemProtect() {
        return userService.getSystemProtect();
    }

    /**
     * 通过用户手机号的部分信息模糊查询用户手机
     *
     * @return 用户手机号列表
     */
    @ApiOperation(value = "通过用户手机号的部分信息模糊查询用户手机", response = PhoneBO.class, notes = "通过用户手机号的部分信息模糊查询用户手机", httpMethod = "GET")
    @LoginAuth
    @RateLimit(key = "limitGetUserPhones")
    @GetMapping("/get-user-phones")
    public PhoneBO getUserPhones(@RequestParam(value = "phone", required = false) String phone,
                                 @RequestParam(value = "page", required = false) Integer page,
                                 @RequestParam(value = "pageSize", required = false) Integer pageSize) {
        return userService.getUserPhones(phone, page, pageSize);
    }

    /**
     * 禁止或者取消用户的相关的操作
     *
     * @param userOperateAuth 用户操作权限PO及持久层对象
     * @return 影响的行数
     */
    @ApiOperation(value = "禁止或者取消用户的相关的操作", notes = "禁止或者取消用户的相关的操作", httpMethod = "POST")
    @LoginAuth
    @RateLimit(key = "limitSetUserOperate")
    @PostMapping("/set-user-operate")
    public int setUserOperate(@RequestBody UserOperateAuth userOperateAuth) {
        return userService.setUserOperate(userOperateAuth);
    }

}
